import { EMPTY_FUNCTION, logger } from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'

type ElementObserverOptions = (element: Element, mutation: MutationRecord, matchedSelector: string | null) => void
type AttributeObserverOptions = (element: Element, mutation: MutationRecord, attributeName: string) => void

interface ObserverOptions {
  selectors?: string | string[]
  tagNames?: string | string[]
  onRemoved?: ElementObserverOptions
  onAdded?: ElementObserverOptions
  onAttributeChange?: AttributeObserverOptions
  logChanges?: boolean
  trackAttributes?: string[] // 监控特定属性变化
  includeSubtree?: boolean // 是否监控子树
}

interface ObserverStats {
  startTime: number
  removedCount: number
  addedCount: number
  attributeChanges: number
  lastChange: {
    type: 'added' | 'removed' | 'attribute'
    element: Element
    attributeName?: string
    time: Date
  } | null
}

export class ObserverUtils {
  private static debugName = 'Observer'

  /**
   * 创建一个 DOM 元素监控器
   */
  static createObserver(
    options: ObserverOptions = {},
    target: Element = document.body,
  ): { disconnect: () => void, observerConfig: MutationObserverInit, getStats: () => ObserverStats } {
    const {
      selectors,
      tagNames,
      onRemoved,
      onAdded,
      onAttributeChange,
      logChanges = false,
      trackAttributes = [],
      includeSubtree = false,
    } = options

    const selectorList = (Array.isArray(selectors) ? selectors : selectors ? [selectors] : []).filter(Boolean)

    // 统计信息
    const stats: ObserverStats = {
      startTime: Date.now(),
      removedCount: 0,
      addedCount: 0,
      attributeChanges: 0,
      lastChange: null,
    }

    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        // 处理节点添加/删除
        if (mutation.type === 'childList') {
          this.processRemovedNodes(mutation, stats, { logChanges, selectorList, tagNames, onRemoved })
          this.processAddedNodes(mutation, stats, { logChanges, selectorList, tagNames, onAdded })
        }

        // 处理属性变化
        if (mutation.type === 'attributes' && trackAttributes.length > 0) {
          this.processAttributeChange(mutation, stats, { logChanges, selectorList, tagNames, trackAttributes, onAttributeChange })
        }
      })
    })

    const observerConfig: MutationObserverInit = {
      childList: true,
      subtree: includeSubtree,
      attributes: trackAttributes.length > 0,
      attributeFilter: trackAttributes.length > 0 ? trackAttributes : undefined,
      characterData: false,
    }

    observer.observe(target, observerConfig)

    return {
      disconnect: () => {
        observer.disconnect()
        if (logChanges)
          logger.info(`[${this.debugName}] ${SYMBOLS.OTHERS.STOP} 停止监控，统计信息:`, stats)
      },
      observerConfig,
      getStats: () => ({ ...stats }),
    }
  }

  /**
   * 处理被删除的节点
   */
  private static processRemovedNodes(
    mutation: MutationRecord,
    stats: ObserverStats,
    options: { logChanges: boolean, selectorList: string[], tagNames?: string | string[], onRemoved?: ElementObserverOptions },
  ): void {
    const { logChanges = false, selectorList, tagNames, onRemoved } = options

    mutation.removedNodes.forEach((node) => {
      if (node.nodeType === Node.ELEMENT_NODE && (tagNames?.includes((node as Element).tagName) || !tagNames)) {
        const element = node as Element
        const matchedSelector = this.findMatchingSelector(element, selectorList)

        if ((selectorList.length > 0 && matchedSelector) || selectorList.length === 0) {
          stats.removedCount++
          stats.lastChange = { type: 'removed', element, time: new Date() }

          if (logChanges)
            this.logRemoval(element, matchedSelector, mutation)

          onRemoved?.(element, mutation, matchedSelector)
        }
      }
    })
  }

  /**
   * 处理新增的节点
   */
  private static processAddedNodes(
    mutation: MutationRecord,
    stats: ObserverStats,
    options: { logChanges: boolean, selectorList: string[], tagNames?: string | string[], onAdded?: ElementObserverOptions },
  ): void {
    const { logChanges = false, selectorList, tagNames, onAdded } = options

    mutation.addedNodes.forEach((node) => {
      if (node.nodeType === Node.ELEMENT_NODE && (tagNames?.includes((node as Element).tagName) || !tagNames)) {
        const element = node as Element
        const matchedSelector = this.findMatchingSelector(element, selectorList)

        if ((selectorList.length > 0 && matchedSelector) || selectorList.length === 0) {
          stats.addedCount++
          stats.lastChange = { type: 'added', element, time: new Date() }

          if (logChanges)
            this.logAddition(element, matchedSelector, mutation)

          onAdded?.(element, mutation, matchedSelector)
        }
      }
    })
  }

  /**
   * 处理属性变化
   */
  private static processAttributeChange(
    mutation: MutationRecord,
    stats: ObserverStats,
    options: { logChanges: boolean, selectorList: string[], tagNames?: string | string[], trackAttributes: string[], onAttributeChange?: AttributeObserverOptions },
  ): void {
    const { logChanges = false, selectorList, tagNames, trackAttributes, onAttributeChange } = options
    const element = mutation.target as Element
    const matchedSelector = this.findMatchingSelector(element, selectorList)
    const attributeName = mutation.attributeName

    if (matchedSelector && attributeName && trackAttributes.includes(attributeName) && (tagNames?.includes(element.tagName) || !tagNames)) {
      stats.attributeChanges++
      stats.lastChange = { type: 'attribute', element, attributeName, time: new Date() }

      if (logChanges)
        this.logAttributeChange(element, matchedSelector, attributeName)

      onAttributeChange?.(element, mutation, attributeName)
    }
  }

  /**
   * 查找匹配的选择器
   */
  private static findMatchingSelector(element: Element, selectors: string[]): string | null {
    for (const selector of selectors) {
      if (element.matches?.(selector) || element.querySelector?.(selector)) {
        return selector
      }
    }
    return null
  }

  /**
   * 记录删除日志
   */
  private static logRemoval(element: Element, selector: string | null, mutation: MutationRecord): void {
    logger.executeWithLogging(`${SYMBOLS.MATH.SUBTRACT} [${this.debugName}] ${element.tagName} 元素被删除`, () => {
      logger.message('匹配的选择器:', selector)
      logger.message('被删除的元素:', element)
      logger.message('ID:', element.id)
      logger.message('类名:', element.className)
      logger.message('Mutation:', mutation)
    }).then(EMPTY_FUNCTION)
  }

  /**
   * 记录添加日志
   */
  private static logAddition(element: Element, selector: string | null, mutation: MutationRecord): void {
    logger.executeWithLogging(`${SYMBOLS.MATH.ADD} [${this.debugName}] ${element.tagName} 元素被添加`, () => {
      logger.message('匹配的选择器:', selector)
      logger.message('新增的元素:', element)
      logger.message('源位置:', '')
      logger.message('Mutation:', mutation)
    }).then(EMPTY_FUNCTION)
  }

  /**
   * 记录属性变化日志
   */
  private static logAttributeChange(element: Element, selector: string, attributeName: string): void {
    logger.executeWithLogging(`${SYMBOLS.STATUS.REFRESH} [${this.debugName}] 属性变化`, () => {
      logger.message('匹配的选择器:', selector)
      logger.message('元素:', element)
      logger.message('属性名:', attributeName)
      logger.message('新值:', element.getAttribute(attributeName))
    }).then(EMPTY_FUNCTION)
  }
}
